import abc

from coin.exchange.util.simple_record import RecordWriter

from coin.exchange.base.kr_ws.ws_client_base import (WsClientHandlerBase, WsClientPrinter)


class WsFeedHandlerBase(metaclass=abc.ABCMeta):
  @abc.abstractmethod
  def on_ticker(self, msg):
    raise NotImplementedError()

  @abc.abstractmethod
  def on_status(self, msg):
    raise NotImplementedError()

  @abc.abstractmethod
  def on_trade(self, msg):
    raise NotImplementedError()

  @abc.abstractmethod
  def on_book(self, msg):
    raise NotImplementedError()


class WsFeedPrinter(WsFeedHandlerBase):
  def __init__(self, *, verbose=True):
    self.verbose = verbose
    self.ticker_count = 0
    self.status_count = 0
    self.trade_count = 0
    self.book_count = 0

  def print_status(self):
    print("WsFeedPrinter: %d %d %d %d" %
          (self.ticker_count, self.status_count, self.trade_count, self.book_count))

  def on_ticker(self, msg):
    self.ticker_count += 1
    if self.verbose:
      print("Ticker", msg)
    else:
      print("Ticker")

  def on_status(self, msg):
    self.status_count += 1
    if self.verbose:
      print("Status", msg)
    else:
      print("Status")

  def on_trade(self, msg):
    self.trade_count += 1
    if self.verbose:
      print("Trade", msg)
    else:
      print("Trade")

  def on_book(self, msg):
    self.book_count += 1
    if self.verbose:
      print("Book", msg)
    else:
      print("Book")


class WsFeedArchiver(WsFeedHandlerBase):
  def __init__(self, *, filename, verbose=True):
    self.filename = filename
    self.verbose = verbose
    self.writer = RecordWriter(filename)

  def on_ticker(self, msg):
    if self.verbose:
      print("Ticker", msg)
    self.writer.write_record(msg.SerializeToString())
    self.writer.flush()

  def on_status(self, msg):
    if self.verbose:
      print("Status", msg)
    self.writer.write_record(msg.SerializeToString())
    self.writer.flush()

  def on_trade(self, msg):
    if self.verbose:
      print("Trade", msg)
    self.writer.write_record(msg.SerializeToString())
    self.writer.flush()

  def on_book(self, msg):
    if self.verbose:
      print("Book", msg)
    self.writer.write_record(msg.SerializeToString())
    self.writer.flush()


class WebsocketParserManagerBase(WsClientHandlerBase):
  def __init__(self, *, handler):
    super().__init__()
    assert isinstance(handler, WsFeedHandlerBase) or handler is None
    self._handler = handler

  def set_handler(self, handler):
    assert isinstance(handler, WsFeedHandlerBase) or handler is None
    self._handler = handler

  def on_open(self):
    pass

  def on_close(self):
    pass

  def on_sent_msg(self, update):
    pass

  def on_recv_msg(self, update):
    pass

  def on_error(self, e, data=None):
    raise NotImplementedError()
